﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YJKArchUtils.Utils;
using YJKRevitRampModule.RampDataManager;
using YJKRevitKernel.ElementSearchUtility.LinkDocumentSuite;
using YJKRevitDimensionText.OneKeyPlanDim.DimData;
using YJKRevitDimensionText.OneKeyPlanDim.LevelDim;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;
using YJKRevitDimensionText.VerticalAutoDim.OutWallSearch;

namespace YJKRevitDimensionText.OneKeyPlanDim
{
	public class PlanDimensionDataManage
	{
		public PlanDimensionDataManage(ExternalCommandData cmdData, Autodesk.Revit.DB.Document doc)
		{
			this.m_doc = doc;
			this.m_cmdData = cmdData;
		}

		public bool TryPreparePlanDimensionData()
		{
			this.GetIintersectsFilter(this.m_doc);
			return this.PrepareData();
		}

		private void GetIintersectsFilter(Autodesk.Revit.DB.Document doc)
		{
			ViewData viewData = new ViewData(this.m_doc.ActiveView as ViewPlan);
			BoundingBoxXYZ cropBox = this.m_doc.ActiveView.CropBox;
			XYZ xyz = this.m_doc.ActiveView.CropBox.Min - new XYZ(10000000.0, 10000000.0, 0.0);
			XYZ xyz2 = this.m_doc.ActiveView.CropBox.Max + new XYZ(10000000.0, 10000000.0, 0.0);
			xyz = new XYZ(xyz.X, xyz.Y, viewData.ViewDepthZ + Common.MMToFeet(5.0));
			xyz2 = new XYZ(xyz2.X, xyz2.Y, viewData.CutHeightZ);
			Outline outline = new Outline(xyz, xyz2);
			this.m_intersectsFilter = new BoundingBoxIntersectsFilter(outline);
			xyz = new XYZ(xyz.X, xyz.Y, viewData.ViewDepthZ - this.m_dFloorDepth);
			outline = new Outline(xyz, xyz2);
			this.m_intersectsFilterFloor = new BoundingBoxIntersectsFilter(outline);
		}

		private bool PrepareData()
		{
			bool result;
			try
			{
				OcclusionArea.SetInstanceToNull();
				KeyComponent.SetInstanceToNull();
				Room2RoomTag.SetInstanceToNull();
				KeyComponent.GetInstance().m_doc = this.m_doc;
				this.m_lstDoc = this.GetAllRevitLinkInstancesInDoc(this.m_doc.ActiveView);
				this.m_lstDoc.Add(this.m_doc);
				KeyComponent.GetInstance().m_lstDoc.AddRange(this.m_lstDoc);
				this.PrepareGrids(out KeyComponent.GetInstance().m_lstDbAxial);
				KeyComponent.GetInstance().m_lstWall = this.prepare_LstElement<Wall>(BuiltInCategory.OST_Walls, false, false);
				this.PrepareParapetLevel();
				if (!this.CalOutWallCurves())
				{
					result = false;
				}
				else
				{
					List<Room> lstRoom = this.prepare_LstElement<Room>(BuiltInCategory.OST_Rooms, false, false);
					List<FamilyInstance> lstFloorDrain = this.prepare_LstElement<FamilyInstance>(BuiltInCategory.OST_PipeAccessory, false, false);
					this.PreapareDbFloorDrain(lstFloorDrain);
					KeyComponent.GetInstance().m_lstDoor = this.prepare_LstElement<FamilyInstance>(BuiltInCategory.OST_Doors, false, false);
					KeyComponent.GetInstance().m_lstWindow = this.prepare_LstElement<FamilyInstance>(BuiltInCategory.OST_Windows, false, false);
					this.PreapareDoorAndWindowTag();
					KeyComponent.GetInstance().m_lstColumn = this.prepare_LstElement<FamilyInstance>(BuiltInCategory.OST_Columns, false, false);
					KeyComponent.GetInstance().m_lstTopographySurface = this.prepare_LstElement<TopographySurface>(BuiltInCategory.OST_Topography, false, false);
					KeyComponent.GetInstance().m_lstBuildingPad = this.prepare_LstElement<BuildingPad>(BuiltInCategory.OST_BuildingPad, false, false);
					this.m_lstGenericModel = this.prepare_LstElement<FamilyInstance>(BuiltInCategory.OST_GenericModel, false, false);
					this.m_lstGroup = this.prepare_LstElement<Group>(BuiltInCategory.OST_IOSModelGroups, false, false);
					this.m_lstFloor = this.prepare_LstElement<Floor>(BuiltInCategory.OST_Floors, false, false);
					this.PrepareDbGutter();
					KeyComponent.GetInstance().m_lstRoof = this.prepare_LstElement<RoofBase>(BuiltInCategory.OST_Roofs, false, false);
					this.PrepareOpening();
					this.PrepareDbSteps();
					this.PrepareDbRampByDoors();
					this.PrepareBarrierFreeRamps();
					this.PrepareDbRevitRamps();
					this.PrepareDbCarRamps();
					this.PrepareDbCanopys();
					this.PreapareRoof();
					this.PrepareSloopFloors();
					this.PreapareFloorLevelDim();
					this.PreapareOutDoorFloorLevelDim();
					Room2RoomTag.GetInstance().SetRoomData(lstRoom, this.m_doc);
					OcclusionArea.GetInstance().CalOcclusionArea();
					result = true;
				}
			}
			catch
			{
				result = false;
			}
			return result;
		}

		private void PreapareDoorAndWindowTag()
		{
			foreach (BuiltInCategory builtInCategory in new List<BuiltInCategory>
			{
				(BuiltInCategory)(-2000460),
				(BuiltInCategory)(-2000450)
			})
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(KeyComponent.GetInstance().m_doc);
				filteredElementCollector.OfCategory(builtInCategory).WhereElementIsNotElementType();
				foreach (Element element in filteredElementCollector)
				{
					IndependentTag independentTag = element as IndependentTag;
					if (independentTag != null)
					{
						ElementId taggedLocalElementId = independentTag.TaggedLocalElementId;
						if (taggedLocalElementId != null && taggedLocalElementId != ElementId.InvalidElementId)
						{
							KeyComponent.GetInstance().m_DicIndependentTag[taggedLocalElementId] = independentTag;
						}
					}
				}
			}
		}

		private void PreapareDbFloorDrain(List<FamilyInstance> lstFloorDrain)
		{
			foreach (FamilyInstance floorDrain in lstFloorDrain)
			{
				DbFloorDrain item = new DbFloorDrain(floorDrain);
				KeyComponent.GetInstance().m_AllDbFloorDrain.Add(item);
			}
		}

		private bool CalOutWallCurves()
		{
			List<OutWallData> outermostWalls = OutRoomOutWallCreator.GetOutermostWalls(new OutRoomOutWallCreator.DetermineAdjacentElementLengthsAndWallAreasDel(OutRoomOutWallCreator.DetermineAdjacentElementLengthsAndWallAreasEx), this.m_doc, this.m_doc.ActiveView, true);
			if (outermostWalls.Count < 3)
			{
				YJKMessageBox.Show("无法搜索到外墙轮廓");
				return false;
			}
			for (int i = 1; i < outermostWalls.Count; i++)
			{
				if (outermostWalls[i - 1].TryMergeCommonOutWall(outermostWalls[i]))
				{
					outermostWalls.RemoveAt(i);
					i--;
				}
				if (i == outermostWalls.Count - 1 && outermostWalls[0].TryMergeCommonOutWall(outermostWalls[outermostWalls.Count - 1]))
				{
					outermostWalls.RemoveAt(outermostWalls.Count - 1);
				}
			}
			foreach (OutWallData outWallData in outermostWalls)
			{
				KeyComponent.GetInstance().m_lstOutWallCurves.Add(outWallData.Curve);
				if (outWallData.Element != null)
				{
					KeyComponent.GetInstance().m_lstOutWallData.Add(outWallData);
				}
			}
			return true;
		}

		private void PrepareParapetLevel()
		{
			List<Wall> list = new List<Wall>();
			foreach (Wall wall in KeyComponent.GetInstance().m_lstWall)
			{
				if (wall.Name.Contains("女儿"))
				{
					list.Add(wall);
				}
			}
			ParapetLevelDim parapetLevelDim = new ParapetLevelDim(this.m_doc, list);
			KeyComponent.GetInstance().m_ParapetLevelDim = parapetLevelDim;
		}

		private List<Document> GetAllRevitLinkInstancesInDoc(Autodesk.Revit.DB.View view)
		{
			IEnumerable<ElementId> enumerable = new FilteredElementCollector(this.m_doc, view.Id).OfClass(typeof(RevitLinkInstance)).ToElementIds();
			List<Document> list = new List<Document>();
			foreach (ElementId elementId in enumerable)
			{
				Element element = this.m_doc.GetElement(elementId);
				if (!(element.GetType() != typeof(RevitLinkInstance)))
				{
					RevitLinkInstance revitLinkInstance = element as RevitLinkInstance;
					if (revitLinkInstance != null)
					{
						Document linkDocument = revitLinkInstance.GetLinkDocument();
						if (linkDocument != null && !string.IsNullOrEmpty(linkDocument.PathName))
						{
							list.Add(linkDocument);
						}
					}
				}
			}
			return list;
		}

		private List<T> prepare_LstElement<T>(BuiltInCategory inputCategory, bool bIsGrid = false, bool bIsOpening = false) where T : Element
		{
			List<T> list = new List<T>();
			FilteredElementCollectorLinkDocument filteredElementCollectorLinkDocument = new FilteredElementCollectorLinkDocument(this.m_doc);
			if (!bIsGrid)
			{
                if ((int)inputCategory == -2000032)
				{
					filteredElementCollectorLinkDocument.AddViewLimit(this.m_intersectsFilterFloor);
				}
				else
				{
					filteredElementCollectorLinkDocument.AddViewLimit(this.m_intersectsFilter);
				}
			}
			if (bIsOpening)
			{
				filteredElementCollectorLinkDocument.OfCalss(typeof(Opening)).WhereElementIsNotElementType();
			}
			else
			{
				filteredElementCollectorLinkDocument.OfCategory(inputCategory);
			}
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in filteredElementCollectorLinkDocument.ToBeans())
			{
				Element useElement = baseLinkDocumentResultBean.UseElement;
				if (baseLinkDocumentResultBean.LstParentRevitLinkInstance.Count <= 1 && useElement is T && useElement.GroupId == ElementId.InvalidElementId)
				{
					list.Add(useElement as T);
				}
			}
			return list;
		}

		private void PrepareGrids(out List<DbAxial> lstDbAxial)
		{
			lstDbAxial = new List<DbAxial>();
			List<Grid> list = this.prepare_LstElement<Grid>(BuiltInCategory.OST_Grids, true, false);
			lstDbAxial = new List<DbAxial>();
			foreach (Grid grid in list)
			{
				if (grid != null && grid.Curve is Line)
				{
					bool flag = false;
					for (int i = 0; i < lstDbAxial.Count; i++)
					{
						if (lstDbAxial[i].IsSameDirection(grid))
						{
							flag = true;
							break;
						}
					}
					if (!flag)
					{
						DbAxial item = new DbAxial(grid);
						lstDbAxial.Add(item);
					}
				}
			}
		}

		private void PrepareOpening()
		{
			List<Opening> collection = this.prepare_LstElement<Opening>(BuiltInCategory.INVALID, true, true);
			KeyComponent.GetInstance().m_lstOpening.AddRange(collection);
			for (int i = 0; i < this.m_lstGenericModel.Count; i++)
			{
				FamilyInstance familyInstance = this.m_lstGenericModel[i];
				if (familyInstance.Symbol.FamilyName.Contains("洞"))
				{
					KeyComponent.GetInstance().m_lstOpening.Add(familyInstance);
					this.m_lstGenericModel.RemoveAt(i);
					i--;
				}
			}
		}

		private void PrepareDbSteps()
		{
			for (int i = 0; i < this.m_lstGenericModel.Count; i++)
			{
				FamilyInstance familyInstance = this.m_lstGenericModel[i];
				if (familyInstance.Symbol.FamilyName.Contains("HYFootstep"))
				{
					DbSteps item = new DbSteps(familyInstance);
					KeyComponent.GetInstance().m_AllDbSteps.Add(item);
					this.m_lstGenericModel.RemoveAt(i);
					i--;
				}
			}
		}

		private void PreapareRoof()
		{
			KeyComponent.GetInstance().m_RoofLevelDim = new RoofLevelDim(this.m_doc);
			new List<Floor>();
			for (int i = 0; i < this.m_lstFloor.Count; i++)
			{
				string name = this.m_lstFloor[i].FloorType.Name;
				if (name.Contains("屋顶") || name.Contains("屋面") || name.Contains("退台") || name.Contains("天台") || name.Contains("露台"))
				{
					KeyComponent.GetInstance().m_RoofLevelDim.AddRoof(this.m_lstFloor[i]);
					this.m_lstFloor.RemoveAt(i);
					i--;
				}
			}
			for (int j = 0; j < KeyComponent.GetInstance().m_lstRoof.Count; j++)
			{
				if (!KeyComponent.GetInstance().m_lstRoof[j].RoofType.Name.Contains("雨棚"))
				{
					KeyComponent.GetInstance().m_RoofLevelDim.AddRoof(KeyComponent.GetInstance().m_lstRoof[j]);
					KeyComponent.GetInstance().m_lstRoof.RemoveAt(j);
					j--;
				}
			}
		}

		private void PrepareDbRampByDoors()
		{
			for (int i = 0; i < this.m_lstGenericModel.Count; i++)
			{
				FamilyInstance familyInstance = this.m_lstGenericModel[i];
				if (familyInstance.Symbol.FamilyName.Contains("入门坡道"))
				{
					DbRampByDoor dbRampByDoor = new DbRampByDoor(familyInstance);
					if (dbRampByDoor.AnalysisInfo())
					{
						Line baseLineFarAwayDoor = dbRampByDoor.BaseLineFarAwayDoor;
						if (!(baseLineFarAwayDoor == null) && baseLineFarAwayDoor.IsBound)
						{
							dbRampByDoor.SetWallInOrOut((baseLineFarAwayDoor.GetEndPoint(0) + baseLineFarAwayDoor.GetEndPoint(1)) / 2.0, KeyComponent.GetInstance().m_lstOutWallCurves);
							KeyComponent.GetInstance().m_AllDbRampByDoor.Add(dbRampByDoor);
							this.m_lstGenericModel.RemoveAt(i);
							i--;
						}
					}
				}
			}
		}

		private void PrepareSloopFloors()
		{
			List<Floor> list = new List<Floor>();
			foreach (Floor floor in this.m_lstFloor)
			{
				if (!(ElementId.InvalidElementId != floor.GroupId))
				{
					DbSlopeFloor dbSlopeFloor = new DbSlopeFloor(floor);
					if (dbSlopeFloor.AnalysisInfo())
					{
						if (dbSlopeFloor.BIsSlopeFloor())
						{
							Line slopeStartLine = dbSlopeFloor.SlopeStartLine;
							if (!(slopeStartLine == null) && slopeStartLine.IsBound)
							{
								dbSlopeFloor.SetWallInOrOut((slopeStartLine.GetEndPoint(0) + slopeStartLine.GetEndPoint(1)) / 2.0, KeyComponent.GetInstance().m_lstOutWallCurves);
								KeyComponent.GetInstance().m_AllDbSlopeFloor.Add(dbSlopeFloor);
							}
						}
						else
						{
							list.Add(floor);
						}
					}
				}
			}
			this.m_lstFloor.Clear();
			this.m_lstFloor.AddRange(list);
		}

		private void PreapareFloorLevelDim()
		{
			KeyComponent.GetInstance().m_floorLevelDim = new FloorLevelDim(this.m_doc);
			foreach (Floor floor in this.m_lstFloor)
			{
				KeyComponent.GetInstance().m_floorLevelDim.AddFloor(floor);
			}
		}

		private void PreapareOutDoorFloorLevelDim()
		{
			KeyComponent.GetInstance().m_OutDoorFloorLevelDim = new OutDoorFloorLevelDim(this.m_doc);
			foreach (TopographySurface ele in KeyComponent.GetInstance().m_lstTopographySurface)
			{
				KeyComponent.GetInstance().m_OutDoorFloorLevelDim.AddBuildingPad(ele);
			}
			foreach (BuildingPad ele2 in KeyComponent.GetInstance().m_lstBuildingPad)
			{
				KeyComponent.GetInstance().m_OutDoorFloorLevelDim.AddBuildingPad(ele2);
			}
		}

		private void PrepareBarrierFreeRamps()
		{
			foreach (Group group in this.m_lstGroup)
			{
				if (BarrierFreeRampManager.IsBarrierFreeRamp(group))
				{
					DbBarrierFreeRamp dbBarrierFreeRamp = new DbBarrierFreeRamp(group);
					if (dbBarrierFreeRamp.AnalysisInfo())
					{
						Line slopeStartLine = dbBarrierFreeRamp.SlopeStartLine;
						if (!(slopeStartLine == null) && slopeStartLine.IsBound)
						{
							dbBarrierFreeRamp.SetWallInOrOut((slopeStartLine.GetEndPoint(0) + slopeStartLine.GetEndPoint(1)) / 2.0, KeyComponent.GetInstance().m_lstOutWallCurves);
							KeyComponent.GetInstance().m_AllDbBarrierFreeRamp.Add(dbBarrierFreeRamp);
						}
					}
				}
			}
		}

		private void PrepareDbRevitRamps()
		{
			foreach (Element ramp in this.prepare_LstElement<Element>(BuiltInCategory.OST_Ramps, false, false))
			{
				DbRevitRamp dbRevitRamp = new DbRevitRamp(ramp);
				if (dbRevitRamp.AnalysisInfo())
				{
					Line slopeStartLine = dbRevitRamp.SlopeStartLine;
					if (!(slopeStartLine == null) && slopeStartLine.IsBound)
					{
						dbRevitRamp.SetWallInOrOut((slopeStartLine.GetEndPoint(0) + slopeStartLine.GetEndPoint(1)) / 2.0, KeyComponent.GetInstance().m_lstOutWallCurves);
						KeyComponent.GetInstance().m_AllDbRevitRamp.Add(dbRevitRamp);
					}
				}
			}
		}

		private void PrepareDbGutter()
		{
			string strGuid = "43FEE925-0EBE-45D8-BA6F-72A4411E065A";
			foreach (Group group in this.m_lstGroup)
			{
				if (CommonInterface.IsHasGuid(group, strGuid))
				{
					DbGutter item = new DbGutter(group, this.m_doc);
					KeyComponent.GetInstance().m_AllDbGutter.Add(item);
				}
			}
		}

		private void PrepareDbCarRamps()
		{
			string strGuid = "D7EA64A1-BA2E-4454-B16C-8C7C9CB7A5B3";
			string strGuid2 = "E9E77A4D-6DFB-4969-8CE4-F03E1F77BFF2";
			List<Floor> list = new List<Floor>();
			for (int i = 0; i < this.m_lstFloor.Count; i++)
			{
				if (CommonInterface.IsHasGuid(this.m_lstFloor[i], strGuid) && CommonInterface.IsHasGuid(this.m_lstFloor[i], strGuid2))
				{
					list.Add(this.m_lstFloor[i]);
					this.m_lstFloor.RemoveAt(i);
					i--;
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				for (int k = j + 1; k < list.Count; k++)
				{
					DbCarRamp dbCarRamp = new DbCarRamp(list[j], list[k]);
					if (dbCarRamp.AnalyserRamp())
					{
						List<Curve> centerLineList = dbCarRamp.CenterLineList;
						if (centerLineList.Count > 0)
						{
							dbCarRamp.SetWallInOrOut((centerLineList[0].GetEndPoint(0) + centerLineList[0].GetEndPoint(1)) / 2.0, KeyComponent.GetInstance().m_lstOutWallCurves);
							KeyComponent.GetInstance().m_AllDbCarRamp.Add(dbCarRamp);
						}
					}
				}
			}
		}

		private void PrepareDbCanopys()
		{
			new List<Floor>();
			for (int i = 0; i < this.m_lstFloor.Count; i++)
			{
				if (this.m_lstFloor[i].FloorType.Name.Contains("雨棚"))
				{
					DbCanopy item = new DbCanopy(this.m_lstFloor[i]);
					KeyComponent.GetInstance().m_lstDbCanopy.Add(item);
					this.m_lstFloor.RemoveAt(i);
					i--;
				}
			}
			for (int j = 0; j < KeyComponent.GetInstance().m_lstRoof.Count; j++)
			{
				if (KeyComponent.GetInstance().m_lstRoof[j].RoofType.Name.Contains("雨棚"))
				{
					DbCanopy item2 = new DbCanopy(KeyComponent.GetInstance().m_lstRoof[j]);
					KeyComponent.GetInstance().m_lstDbCanopy.Add(item2);
					KeyComponent.GetInstance().m_lstRoof.RemoveAt(j);
					j--;
				}
			}
		}

		private ExternalCommandData m_cmdData;

		private Document m_doc;

		private List<Document> m_lstDoc = new List<Document>();

		private BoundingBoxIntersectsFilter m_intersectsFilter;

		private BoundingBoxIntersectsFilter m_intersectsFilterFloor;

		private double m_dFloorDepth = Common.MMToFeet(1000.0);

		private List<FamilyInstance> m_lstGenericModel = new List<FamilyInstance>();

		private List<Group> m_lstGroup = new List<Group>();

		private List<Floor> m_lstFloor = new List<Floor>();
	}
}
